/* 
 * Copyright (C) 2012 UTSChedule
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package utsc.apps.utschedule.ui.activities;

import java.util.ArrayList;
import java.util.Calendar;

import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;

import android.app.DatePickerDialog.OnDateSetListener;
import android.app.TimePickerDialog.OnTimeSetListener;
import android.content.Intent;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TimePicker;
import android.widget.Toast;
import utsc.apps.utschedule.R;
import utsc.apps.utschedule.UTSCheduleApp;
import utsc.apps.utschedule.classes.Course;
import utsc.apps.utschedule.classes.Exam;
import utsc.apps.utschedule.classes.Timetable;
import utsc.apps.utschedule.ui.MessageDialogFragment;
import utsc.apps.utschedule.ui.MyTimePickerDialogFragment;
import utsc.apps.utschedule.ui.activities.adapters.CourseSpinnerAdapter;
import utsc.apps.utschedule.ui.interfaces.TimetableActivity;
import utsc.apps.utschedule.util.AppUtils;
import utsc.apps.utschedule.util.TimetableHelper;
import utsc.apps.utschedule.util.GenericActionModeCallback.OnMenuItemClickedListener;
import utsc.apps.utschedule.util.Validator;
import utsc.apps.utschedule.util.database.DatabaseManager;

/**
 * A form liked activity for create/update an {@link Exam exam} object.
 *
 */
public class ExamFormActivity extends GenericFormActivity<Exam> implements OnMenuItemClickedListener, OnDateSetListener,OnTimeSetListener,OnClickListener {

	private Spinner _spinnerCourses;
	private EditText _txtWeight;
	private EditText _txtDate;
	private EditText _txtStarttime;
	private EditText _txtEndtime;
	private EditText _txtLocation;
	private EditText _txtMark;
	private EditText _txtTotal;
	private Exam _exam;
	private ArrayList<Course> _courseList;
	private CourseSpinnerAdapter _courseSpinnerAdapter;
	private EditText _currentEditingTimeView;
	private EditText _currentEditingDateView;
	private int _selectedCoursePos;
	private RadioGroup _radioGrpType;
	private final String TAG="ExamFormActivity";
	private final Validator _validator=Validator.newInstance(TAG);  
	
	@Override
	protected void onCreate(Bundle arg0) {
		super.onCreate(arg0);
		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
		setupBasicResources();
		Intent requestIntent=getIntent();
		if (requestIntent!=null) {
			_requestCode=requestIntent.getIntExtra("RequestCode", TimetableActivity.RESULT_NEW_EXAM);
		}
		setContentView(R.layout.activity_exam_form);
		setupBasicResources();
		//setup the form based on the request code
		if (_requestCode==TimetableActivity.RESULT_NEW_EXAM) {
			setupResourcesForNew(requestIntent);
		}else {
			setupResourcesForUpdate(requestIntent);
		}
		
	}
	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		onMenuItemClicked(item);
		return true;
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		//setup the option menu based on the request code as well
		if (_requestCode==TimetableActivity.RESULT_NEW_EXAM) {
			getSupportMenuInflater().inflate(R.menu.add_cancel_menu, menu);
		}else {
			getSupportMenuInflater().inflate(R.menu.update_cancel_menu_items, menu);
		}
		return true;
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		UTSCheduleApp app=(UTSCheduleApp) getApplication();
		Timetable timetable=app.get_currentActiveTimetable();
		
		//setup the course selection dropdown
		if (timetable!=null) {
			if (_courseList==null) {
				_courseList=new ArrayList<Course>(DatabaseManager.getInstance(this).getCoursesWithoutTutorials(timetable.get_timetableID()));	
			}
			
			if (_courseSpinnerAdapter==null) {
				_courseSpinnerAdapter=new CourseSpinnerAdapter(this, android.R.layout.simple_spinner_item, _courseList);
				_courseSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
				_spinnerCourses.setAdapter(_courseSpinnerAdapter);
			}
			
			if (_requestCode==TimetableActivity.RESULT_UPDATE_EXAM) {
				_selectedCoursePos=_courseSpinnerAdapter.getCoursePosition(_exam.get_course().get_courseID());
			}
			_spinnerCourses.setSelection(_selectedCoursePos);
			
		}
		
	}
	
	@Override
	protected void setupBasicResources() {
		setContentView(R.layout.activity_exam_form);
		_spinnerCourses=(Spinner) findViewById(R.id.frm_spinner_courses);
		_txtWeight=(EditText) findViewById(R.id.frm_txt_weight);
		_txtDate=(EditText) findViewById(R.id.frm_txt_date);
		_txtStarttime=(EditText) findViewById(R.id.frm_txt_starttime);
		_txtEndtime=(EditText) findViewById(R.id.frm_txt_endtime);
		_txtLocation=(EditText) findViewById(R.id.frm_txt_location);
		_radioGrpType=(RadioGroup) findViewById(R.id.frm_radiogrp_examtype);
		_txtMark=(EditText) findViewById(R.id.frm_txt_mark);
		_txtTotal=(EditText) findViewById(R.id.frm_txt_total);
		_txtDate.setOnClickListener(this);
		_txtStarttime.setOnClickListener(this);
		_txtEndtime.setOnClickListener(this);
		
		_txtEndtime.addTextChangedListener(new TextWatcher() {
			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {}
			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
			@Override
			public void afterTextChanged(Editable s) {
				final Calendar currentStartTime=TimetableHelper.convertFromDateTimeString(_txtStarttime.getText().toString(), TimetableHelper.TYPE_TIME);
				final Calendar currentEndTime=TimetableHelper.convertFromDateTimeString(s.toString(), TimetableHelper.TYPE_TIME);
				//show an error message when the selected time is not a valid end time
				if (!currentEndTime.after(currentStartTime)) {
					Toast.makeText(ExamFormActivity.this, "End time cannot set before the Start time.", Toast.LENGTH_LONG).show();
					showTimePickerDialog(currentEndTime, false, ExamFormActivity.this);
				}else {
					//otherwise, remove the dialog from fragment stack
					removeFragment(MyTimePickerDialogFragment.TAG).commit();
				}
			}
		});
	}

	@Override
	protected void setupResourcesForNew(Intent requestIntent) {
		final Object savedData=getLastCustomNonConfigurationInstance();
		String defaultDate=TimetableHelper.getFormattedString(System.currentTimeMillis(), TimetableHelper.TYPE_DATE);
		String defaultStarttime=TimetableHelper.getHourString(8,0);
		String defaultEndtime=TimetableHelper.getHourString(9,0);
		String defaultWeight="0";
		if (savedData!=null) {
			final Bundle b=(Bundle) savedData;
			_selectedCoursePos=b.getInt(Exam.COURSE, 0);
		}
		
		_txtWeight.setText(defaultWeight);
		_txtDate.setText(defaultDate);
		_txtStarttime.setText(defaultStarttime);
		_txtEndtime.setText(defaultEndtime);
		
	}

	@Override
	public Object onRetainCustomNonConfigurationInstance() {
		Bundle bundle=new Bundle();
		bundle.putInt(Exam.COURSE, _spinnerCourses.getSelectedItemPosition());
		return bundle;
	}
	
	@Override
	protected void setupResourcesForUpdate(Intent requestIntent) {
		_exam=new Exam(requestIntent);
		String defaultDate = null;
		String defaultStartTime=null;
		String defaultEndTime=null;
		String defaultLocation=null;
		String defaultWeight="0";
		String defaultMark=null;
		String defaultTotal=null;
		
		_radioGrpType.check(_exam.get_type()==Exam.TYPE_MIDTERM?R.id.frm_radio_exam_midterm:R.id.frm_radio_midterm_final);
		findViewById(R.id.frm_radio_exam_midterm).setEnabled(false);
		findViewById(R.id.frm_radio_midterm_final).setEnabled(false);
		
		defaultWeight=Double.toString(_exam.get_weight());
		defaultDate=TimetableHelper.getFormattedString(_exam.get_startTime(), TimetableHelper.TYPE_DATE);
		defaultStartTime=TimetableHelper.getFormattedString(_exam.get_startTime(), TimetableHelper.TYPE_TIME);
		defaultEndTime=TimetableHelper.getFormattedString(_exam.get_endTime(), TimetableHelper.TYPE_TIME);
		defaultLocation=_exam.get_location();
		defaultMark=Double.toString(_exam.get_mark());
		defaultTotal=Double.toString(_exam.get_total());
		
		//only show the mark and total field when the exam is finished
		if (_exam.is_expired()) {
			findViewById(R.id.frm_grade).setVisibility(View.VISIBLE);
		 }
		
		_txtWeight.setText(defaultWeight);
		_txtDate.setText(defaultDate);
		_txtStarttime.setText(defaultStartTime);
		_txtEndtime.setText(defaultEndTime);
		_txtLocation.setText(defaultLocation);
		_txtMark.setText(defaultMark);
		_txtTotal.setText(defaultTotal);
	}

	@Override
	protected boolean validate(Exam object) {
		_validator.reset();
		_validator.checkTimeInterval(object.get_startTime(), object.get_endTime(), 1, 0, AppUtils.ERROR_MESSAGE_EXAM_TIME);
		_validator.checkNull(object.get_location(), AppUtils.ERROR_MESSAGE_EXAM_LOCATION);
		if (_validator.get_errorMessages()==null) {
			return true;
		}
		return false;
	}

	@Override
	public void onMenuItemClicked(MenuItem item) {
		int itemID=item.getItemId();
		String dialogTitle=itemID==R.id.add?AppUtils.ERROR_TITLE_EXAM_ADD:AppUtils.ERROR_TITLE_EXAM_UPDATE;
		if (itemID!=R.id.cancel && itemID!=android.R.id.home) {
			
			setupExam();
			//form validation
			if (validate(_exam)) {
				//validation is passed
				final int saveResult=DatabaseManager.getInstance(this).saveExam(_exam);
				
				//check the save result
				//we allow each course to have only two exams (midterm/final)
				//otherwise the save is failed
				if (saveResult==1) {
					if(itemID== R.id.add){
						Toast.makeText(this, AppUtils.TOAST_ADD_EXAM_SUCCESSFULLY_STRING, Toast.LENGTH_SHORT).show();	
						setResult(RESULT_OK);
					}else{ 
						Toast.makeText(this, AppUtils.TOAST_UPDATE_EXAM_SUCCESSFULLY_STRING, Toast.LENGTH_SHORT).show();	
						Intent resultIntent=new Intent();
						resultIntent.putExtra(Exam.EXAMID, _exam.get_examId());
						setResult(RESULT_OK, resultIntent);
					}
					finish();
				}else {
					if (saveResult==-1) {
						showDialogFragment(MessageDialogFragment.newInstance(dialogTitle, AppUtils.ERROR_MESSAGE_EXAM_MAX_EXAM), MessageDialogFragment.TAG);
					}else {
						showDialogFragment(MessageDialogFragment.newInstance(dialogTitle, AppUtils.ERROR_MESSAGE_EXAM_GRADE_SAVED_FAILED), MessageDialogFragment.TAG);
					}
				}
				
			}else {
				showDialogFragment(MessageDialogFragment.newInstance(dialogTitle, _validator.get_errorMessages()), MessageDialogFragment.TAG);
			}
			
		}else {
			if (_requestCode==TimetableActivity.RESULT_NEW_EXAM) {
				Toast.makeText(this, AppUtils.TOAST_ADD_EXAM_CANCELLED_STRING, Toast.LENGTH_SHORT).show();
			}else {
				Toast.makeText(this, AppUtils.TOAST_UPDATE_EXAM_CANCELLED_STRING, Toast.LENGTH_SHORT).show();
			}
			
			finish();
		}
	}
	
	@Override
	public void onDateSet(DatePicker view, int year, int monthOfYear,
			int dayOfMonth) {
		Calendar cal = Calendar.getInstance();
		cal.set(year, monthOfYear, dayOfMonth);
		String selectedDate = TimetableHelper.getFormattedString(cal.getTimeInMillis(), TimetableHelper.TYPE_DATE);
		_currentEditingDateView.setText(selectedDate);
	}
	
	@Override
	public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
		view.setCurrentHour(hourOfDay);
		view.setCurrentMinute(minute);
		_currentEditingTimeView.setText(TimetableHelper.getHourString(hourOfDay, minute));
	}
	
	private void onEditTime(EditText textView){
		_currentEditingTimeView=textView;
		AppUtils.hideKeyBoard(this, textView);
		final Calendar currentTimeSelection=TimetableHelper.convertFromDateTimeString(textView.getText().toString(), TimetableHelper.TYPE_TIME);
		if (currentTimeSelection!=null) {
			showTimePickerDialog(currentTimeSelection, false, this);
		}
	}
	
	/**
	 * Setup the {@link Exam exam} object by collecting the data from the form.
	 */
	private void setupExam(){
		if (_requestCode==TimetableActivity.RESULT_NEW_EXAM) {
			_exam=new Exam();
		}else {
			_exam.set_mark(Double.parseDouble(_txtMark.getText().toString()));
			_exam.set_total(Double.parseDouble(_txtTotal.getText().toString()));
		}
		
		Course selectedCourse=_courseList.get(_spinnerCourses.getSelectedItemPosition());
		UTSCheduleApp app=(UTSCheduleApp) getApplication();
		selectedCourse.set_timetable(app.get_currentActiveTimetable());
		_exam.set_course(selectedCourse);
		_exam.set_type(_radioGrpType.getCheckedRadioButtonId()==R.id.frm_radio_exam_midterm?Exam.TYPE_MIDTERM:Exam.TYPE_FINAL);
		
		double weight = 0;
		String weightTxt=_txtWeight.getText().toString();
		if(weightTxt!=null){
			weight=Double.parseDouble(weightTxt);
		}
		
		_exam.set_weight(weight);
		String date=_txtDate.getText().toString();
		String startTime=date+" "+_txtStarttime.getText().toString();
		String endTime=date+" "+_txtEndtime.getText().toString();
		_exam.set_startTime(TimetableHelper.convertFromDateTimeStringToMillis(startTime, TimetableHelper.TYPE_DATETIME).getTime());
		_exam.set_endTime(TimetableHelper.convertFromDateTimeStringToMillis(endTime, TimetableHelper.TYPE_DATETIME).getTime());
		_exam.set_location(_txtLocation.getText().toString());
	}
	
	private void onEditDate(EditText textView){
		_currentEditingDateView=textView;
		AppUtils.hideKeyBoard(this, textView);
		final Calendar currentDateSelection=TimetableHelper.convertFromDateTimeString(textView.getText().toString(), TimetableHelper.TYPE_DATE);
		if (currentDateSelection!=null) {
			showDatePickerDialog(currentDateSelection, false, this);
		}
	}
	
	@Override
	public void onClick(View v) {
		int id=v.getId();
		switch (id) {
		case R.id.frm_txt_date:
			onEditDate(_txtDate);
			break;
		case R.id.frm_txt_starttime:
			onEditTime(_txtStarttime);
			break;
		case R.id.frm_txt_endtime:
			onEditTime(_txtEndtime);
			break;
		default:
			break;
		}
	}

}
